package swim.sessionbeans;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Set;

import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.jboss.ejb3.annotation.RemoteBinding;

import swim.entitybeans.Abilita;
import swim.entitybeans.Aiuto;
import swim.entitybeans.Amicizia;
import swim.entitybeans.Macroarea;
import swim.entitybeans.Messaggi;
import swim.entitybeans.NuovaAbilita;
import swim.entitybeans.Utente;
import swim.entitydata.DatiAiuto;
import swim.entitydata.DatiAmicizia;
import swim.entitydata.DatiMessaggio;
import swim.entitydata.DatiRichiesteAbilita;
import swim.entitydata.DatiUtente;

@Stateless
@RemoteBinding(jndiBinding = "UtilBeanRemote")
public class UtilBean implements UtilBeanRemote {

	@PersistenceContext(unitName = "swim")
	private EntityManager manager;

	@Override
	public List<String> getMacroareaList() {
		Query q = manager.createQuery("SELECT nome FROM Macroarea");
		List<String> list = castList(String.class, q.getResultList());

		return list;
	}

	@Override
	public List<String> getAbilitaList(String nomeMacroarea) {
		Set<Abilita> set = manager.find(Macroarea.class, nomeMacroarea)
				.getAbilita();
		List<String> list = new ArrayList<String>();
		for (Abilita a : set) {
			list.add(a.getNome());
		}
		return list;
	}

	@Override
	public List<String[]> ricerca(String id, String abilita, String citta) {

		Query q = manager
				.createQuery("SELECT DISTINCT u.nome, u.cognome, u.aiuto_dato, u.aiuto_ricevuto, u.id FROM Utente as u join u.abilita as a WHERE citta= :citta AND a.nome= :abilita AND u.id <> :id ORDER BY (u.aiuto_dato - u.aiuto_ricevuto) DESC");
		Query q1 = manager
				.createQuery("SELECT DISTINCT u.nome, u.cognome, u.aiuto_dato, u.aiuto_ricevuto, u.id FROM Utente as u join u.abilita as a WHERE citta<> :citta AND a.nome= :abilita AND u.id <> :id ORDER BY (u.aiuto_dato - u.aiuto_ricevuto) DESC");
		q.setParameter("id", Long.parseLong(id));
		q.setParameter("citta", citta);
		q.setParameter("abilita", abilita);
		
		q1.setParameter("id", Long.parseLong(id));
		q1.setParameter("citta", citta);
		q1.setParameter("abilita", abilita);
		List<String[]> resultList = q.getResultList();
		resultList.addAll(q1.getResultList());

		return resultList;
	}

	@Override
	public Utente getUtente(Long id) {
		return manager.find(Utente.class, id);
	}

	@Override
	public List<DatiUtente> getListaAmici(String id) {
		List<DatiUtente> returnList = new ArrayList<DatiUtente>();
		Long idL = Long.valueOf(id);
		// Query q1 =
		// manager.createQuery("SELECT DISTINCT u1 FROM Utente AS u join u.amicizie_richieste AS a join a.richiedente AS u1 WHERE u.id = :id AND a.stato= 1");
		Query q1 = manager
				.createQuery("SELECT a.ricevente.id, a.ricevente.nome, a.ricevente.cognome FROM Amicizia a WHERE a.richiedente.id= :id AND stato=true");
		q1.setParameter("id", idL); // SELECT DISTINCT u1.id, u1.nome,
									// u1.cognome FROM Amicizia AS a join
									// a.ricevente AS u join a.richiedente AS u1
									// WHERE a.ricevente = :id AND a.stato= 1");
		Query q2 = manager
				.createQuery("SELECT a.richiedente.id, a.richiedente.nome, a.richiedente.cognome FROM Amicizia a WHERE a.ricevente.id= :id AND stato=true");
		q2.setParameter("id", idL);
		List<Object[]> list = q1.getResultList();
		list.addAll(q2.getResultList());
		for (Object[] o : list) {
			returnList.add(new DatiUtente(((Long) o[0]).toString(),
					(String) o[1], (String) o[2]));
		}
		return returnList;
	}

	@Override
	public List<DatiUtente> cercaTraContatti(String id, String stringa) {
		List<DatiUtente> listaAmici = getListaAmici(id);
		List<DatiUtente> resultList = new ArrayList<DatiUtente>();
		// controllo con nome e cognome nella stessa stringa
		if (stringa.contains(" ")) {

			String[] nomeCognome = stringa.split(" ");
			for (DatiUtente u : listaAmici) {
				if (u.getNome().equals(nomeCognome[0])) {
					if (u.getCognome().equals(nomeCognome[1])) {
						resultList.add(u);
					}
				} else if (u.getCognome().equals(nomeCognome[0])) {
					if (u.getNome().equals(nomeCognome[1])) {
						resultList.add(u);
					}
				}
			}
		} else { // controllo solo nome o cognome
			for (DatiUtente u : listaAmici) {
				if (u.getNome().equals(stringa)
						|| u.getCognome().equals(stringa)) {
					resultList.add(u);
				}
			}
		}

		return resultList;

	}

	@Override
	public List<DatiAiuto> getListaAiuti(String id) {
		List<DatiAiuto> returnList = new ArrayList<DatiAiuto>();
		Long idL = Long.valueOf(id);
		Query q1 = manager
				.createQuery("SELECT a.id, a.titolo, a.dato_da.nome, a.dato_da.cognome, a.ricevuto_da.nome, a.ricevuto_da.cognome, a.stato, a.visualizzato, a.rifiutato, a.data, a.chiuso, a.dato_da.id, a.ricevuto_da.id FROM Aiuto a WHERE a.dato_da.id= :id OR a.ricevuto_da.id= :id ORDER BY a.data DESC");
		q1.setParameter("id", idL);
		List<Object[]> list = q1.getResultList();
		
		for (Object[] o : list) {
			returnList.add(new DatiAiuto(((Long) o[0]).toString(),
					(String) o[1], (String) o[2] + " " + (String) o[3],
					(String) o[4] + " " + (String) o[5], (Boolean) o[6],
					(Boolean) o[7], (Boolean) o[8], (Date) o[9],
					(Boolean) o[10], ((Long) o[11]).toString(), ((Long) o[12])
							.toString(), getIdMittenteUltimoMessaggio(((Long) o[0]).toString())));
		}
		return returnList;
	}
	
	@Override
	public List<DatiAiuto> getRichiesteAiuto(String id) {
		List<DatiAiuto> returnList = new ArrayList<DatiAiuto>();
		Long idL = Long.valueOf(id);
		Query q1 = manager
				.createQuery("SELECT a.id, a.titolo, a.dato_da.nome, a.dato_da.cognome, a.ricevuto_da.nome, a.ricevuto_da.cognome, a.stato, a.visualizzato, a.rifiutato, a.data, a.chiuso, a.dato_da.id, a.ricevuto_da.id FROM Aiuto a WHERE a.stato=:stato AND (a.dato_da.id= :id OR a.ricevuto_da.id= :id) ORDER BY a.data DESC");
		q1.setParameter("id", idL);
		q1.setParameter("stato", false);
		List<Object[]> list = q1.getResultList();
		
		for (Object[] o : list) {
			returnList.add(new DatiAiuto(((Long) o[0]).toString(),
					(String) o[1], (String) o[2] + " " + (String) o[3],
					(String) o[4] + " " + (String) o[5], (Boolean) o[6],
					(Boolean) o[7], (Boolean) o[8], (Date) o[9],
					(Boolean) o[10], ((Long) o[11]).toString(), ((Long) o[12])
							.toString(),"-1"));
		}
		return returnList;
	}

	@Override
	public List<DatiMessaggio> getListaMessaggi(String id_aiuto) {
		Long idL = Long.valueOf(id_aiuto);
		// Query q1 =
		// manager.createQuery("SELECT a.messaggi, a.messaggi.testo FROM Aiuto a WHERE a.id= :id ORDER BY a.messaggi.data DESC");
		Query q1 = manager
				.createQuery("SELECT m.mittente.nome, m.testo FROM Messaggi m WHERE m.aiuto.id= :id ORDER BY m.data DESC");
		q1.setParameter("id", idL);
		List<Object[]> list = q1.getResultList();
		List<DatiMessaggio> retList = new ArrayList<DatiMessaggio>();
		for (Object[] o : list) {
			retList.add(new DatiMessaggio((String) o[0], (String) o[1]));
		}

		return retList;
	}

	private <T> List<T> castList(Class<? extends T> clazz, Collection<?> c) {
		List<T> r = new ArrayList<T>(c.size());
		for (Object o : c)
			r.add(clazz.cast(o));
		return r;
	}

	@Override
	public void inserisciMessaggio(String id_aiuto, String id_mittente,
			String testo) {
		Messaggi messaggio = new Messaggi();
		Aiuto a = manager.find(Aiuto.class, Long.valueOf(id_aiuto));
		messaggio.setAiuto(a);
		Utente u = manager.find(Utente.class, Long.valueOf(id_mittente));
		messaggio.setMittente(u);
		messaggio.setTesto(testo);
		messaggio.setData(new Date());
		messaggio.getAiuto().setData(new Date());
		a.setVisualizzato(false);

		manager.persist(messaggio);
	}

	@Override
	public void richiediAmicizia(String id_richiedente, String id_ricevente) {
		Amicizia amicizia = new Amicizia();
		Utente u1 = manager.find(Utente.class, Long.parseLong(id_richiedente));
		amicizia.setRichiedente(u1);
		Utente u2 = manager.find(Utente.class, Long.parseLong(id_ricevente));
		amicizia.setRicevente(u2);
		amicizia.setStato(false);

		manager.persist(amicizia);
	}

	@Override
	public void accettaAmicizia(String id) {
		Amicizia a = manager.find(Amicizia.class, Long.parseLong(id));
		a.setStato(true);
	}

	@Override
	public void rifiutaAmicizia(String id) {
		Amicizia a = manager.find(Amicizia.class, Long.parseLong(id));
		manager.remove(a);
	}

	@Override
	public String richiediAiuto(String id_richiedente, String id_destinatario,
			String titolo) {
		Aiuto aiuto = new Aiuto();
		Utente u1 = manager.find(Utente.class, Long.valueOf(id_richiedente));
		aiuto.setRicevuto_da(u1);
		Utente u2 = manager.find(Utente.class, Long.valueOf(id_destinatario));
		aiuto.setDato_da(u2);
		aiuto.setTitolo(titolo);
		aiuto.setStato(false);
		aiuto.setVisualizzato(false);
		aiuto.setData(new Date());
		aiuto.setRifiutato(false);
		manager.persist(aiuto);
		
		return aiuto.getId().toString();
	}

	@Override
	public void accettaAiuto(String id_aiuto) {
		Aiuto a = manager.find(Aiuto.class, Long.valueOf(id_aiuto));
		a.setStato(true);
		a.setVisualizzato(true);
	}

	@Override
	public void rifiutaAiuto(String id_aiuto) {
		Aiuto a = manager.find(Aiuto.class, Long.valueOf(id_aiuto));
		a.setRifiutato(true);
	}

	@Override
	public void modificaDati(String id, String email_login, String password,
			String nome, String cognome, String telefono,
			String email_contatto, String citta, String descrizione) {
		Utente utente = manager.find(Utente.class, Long.valueOf(id));
		utente.setEmail_login(email_login);
		utente.setPassword(password);
		utente.setNome(nome);
		utente.setCognome(cognome);
		utente.setTelefono(telefono);
		utente.setEmail_contatto(email_contatto);
		utente.setCitta(citta);
		utente.setDescrizione(descrizione);
	}

	@Override
	public void modificaFoto(String id, String nomeFile, boolean foto) {
		String path = System.getProperty("user.dir");
		File f_old = new File(path + "/img/" + id + ".jpg");
		f_old.delete();
		File f_new = new File(path + "/img/" + nomeFile);
		File f_new_renamed = new File(path + "/img/" + id + ".jpg");
		f_new.renameTo(f_new_renamed);
	}

	@Override
	public void aggiungiAbilita(String id, List<String> abilita) {
		Utente u = manager.find(Utente.class, Long.valueOf(id));
		for (String a : abilita) {
			Query q = manager.createQuery("SELECT id FROM Abilita WHERE nome='"
					+ a + "'");
			Abilita a1 = manager.find(Abilita.class, q.getSingleResult());
			u.addAbilita(a1);
		}

	}

	@Override
	public void rimuoviAbilita(String id, List<String> abilita) {
		Utente u = manager.find(Utente.class, Long.valueOf(id));
		for (String a : abilita) {
			Query q = manager.createQuery("SELECT id FROM Abilita WHERE nome='"
					+ a + "'");
			Abilita a1 = manager.find(Abilita.class, q.getSingleResult());
			u.getAbilita().remove(a1);
		}
	}

	@Override
	public boolean isAmico(String utente1, String utente2) {
		/*
		 * List<DatiUtente> listaAmici = getListaAmici(utente1); for(DatiUtente
		 * u: listaAmici){ if(u.getId().equals(utente2)){ return true; } }
		 */
		Long u = Long.valueOf(utente1);
		Long u1 = Long.valueOf(utente2);
		Query q = manager
				.createQuery("SELECT id FROM Amicizia a WHERE (a.ricevente.id = :id1 AND a.richiedente.id = :id2) OR (a.richiedente.id = :id1 AND a.ricevente.id = :id2)");
		q.setParameter("id1", u);
		q.setParameter("id2", u1);
		if (q.getResultList().size() != 0) {
			return true;
		}
		return false;
	}

	@Override
	public void chiudiAiuto(String id) {
		Aiuto a = manager.find(Aiuto.class, Long.valueOf(id));
		a.setChiuso(true);
	}

	@Override
	public void inviaFeedback(String idAiuto, String feed) {
		Aiuto a = manager.find(Aiuto.class, Long.valueOf(idAiuto));
		a.getRicevuto_da().setAiuto_ricevuto(Long.valueOf(feed));
		a.getDato_da().setAiuto_dato(Long.valueOf(feed));
	}

	@Override
	public List<DatiAmicizia> getRichiesteAmicizia(String id) {
		List<DatiAmicizia> returnList = new ArrayList<DatiAmicizia>();
		Long idL = Long.valueOf(id);
		Query q1 = manager
				.createQuery("SELECT a.id, a.richiedente.nome, a.richiedente.cognome, a.richiedente.id FROM Amicizia a WHERE a.ricevente.id= :id AND a.stato=:stato");
		q1.setParameter("id", idL);
		q1.setParameter("stato", false);
		List<Object[]> list = q1.getResultList();
		for (Object[] o : list) {
			returnList.add(new DatiAmicizia(((Long) o[0]).toString(),
					(String) o[1] + " " + (String) o[2], ((Long) o[3]).toString()));
		}
		return returnList;
	}

	@Override
	public DatiAiuto getAiuto(String id) {
		Aiuto a = manager.find(Aiuto.class, Long.valueOf(id));
		DatiAiuto datiAiuto = new DatiAiuto(id, a.getTitolo(), a.getDato_da()
				.getNome(), a.getRicevuto_da().getNome(), a.isStato(),
				a.isVisualizzato(), a.isVisualizzato(), a.getData(),
				a.isChiuso(), String.valueOf(a.getDato_da().getId()),
				String.valueOf(a.getRicevuto_da().getId()),"-1");
		return datiAiuto;
	}

	@Override
	public void richiediAbilita(String id, String nome, String descrizione) {
		NuovaAbilita na = new NuovaAbilita();
		na.setRichiedente(manager.find(Utente.class, Long.valueOf(id)));
		na.setNome(nome);
		na.setDescrizione(descrizione);
		na.setStato(false);
		na.setVisualizzato(false);
		manager.persist(na);

	}

	@Override
	public void setAiutoAsVisualizzato(String idAiuto) {
		Aiuto a = manager.find(Aiuto.class, Long.valueOf(idAiuto));
		a.setVisualizzato(true);
	}

	@Override
	public String getIdMittenteUltimoMessaggio(String idAiuto) {
		Aiuto a = manager.find(Aiuto.class, Long.valueOf(idAiuto));
		Query q = manager
				.createQuery("SELECT m FROM Messaggi m WHERE m.aiuto=:aiuto ORDER BY m.data DESC");
		q.setParameter("aiuto", a);
		q.setMaxResults(1);
		Messaggi m = (Messaggi)q.getSingleResult();
		return m.getMittente().getId().toString();
	}

}
